package com.kelaite.procurement.service.impl;

import io.jsonwebtoken.lang.Collections;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kelaite.procurement.dto.PipelineHeaderDTO;
import com.kelaite.procurement.dto.PipelinePublicDTO;
import com.kelaite.procurement.dto.VendorDTO;
import com.kelaite.procurement.entity.TPipelineHeader;
import com.kelaite.procurement.entity.TPipelinePublic;
import com.kelaite.procurement.entity.TVendor;
import com.kelaite.procurement.exception.BusinessException;
import com.kelaite.procurement.repository.PipelineItemRepository;
import com.kelaite.procurement.repository.PipelinePublicRepository;
import com.kelaite.procurement.service.PipelinePublicService;
import com.kelaite.procurement.utils.ConvertUtil;
import com.kelaite.procurement.utils.CurrentUserUtils;

@Service
@Transactional
public class PipelinePublicServiceImpl implements PipelinePublicService {

	@Autowired
	private PipelinePublicRepository pipelinePublicRepository;

	@Autowired
	private PipelineItemRepository pipelineItemRepository;

	@PersistenceContext
	private EntityManager em;

	@Override
	public TPipelinePublic save(TPipelinePublic persistence) {

		return this.pipelinePublicRepository.save(persistence);
	}

	@Override
	public TPipelinePublic getObject(Long id) {

		return this.pipelinePublicRepository.findOne(id);
	}

	@Override
	public List<TPipelinePublic> getAll() {

		return this.pipelinePublicRepository.findAll();
	}

	@Override
	public void deleteByObject(TPipelinePublic persistence) {

		this.pipelinePublicRepository.delete(persistence);
	}

	@Override
	public void deleteByPrimaryKey(Long id) {

		this.pipelinePublicRepository.delete(id);
	}

	@SuppressWarnings({ "unchecked", "deprecation" })
	@Override
	public List<TPipelinePublic> getByProperty(String property, Object value) {

		Session session = (org.hibernate.Session) em.getDelegate();
		Criteria criteria = session.createCriteria(TPipelinePublic.class).add(
				org.hibernate.criterion.Expression.eq(property, value));
		return criteria.list();
	}

	@Override
	public List<PipelinePublicDTO> getPipelinePublicListByPipelineId(
			Long pipelineId) {

		List<TPipelinePublic> dbPipelinePublicList = pipelinePublicRepository
				.findByPipelineId(pipelineId);
		if (Collections.isEmpty(dbPipelinePublicList)) {
			throw new BusinessException(String.format(
					"no pipelinePublic for pipelineId[%s]", pipelineId));
		}
		List<PipelinePublicDTO> rt = new ArrayList<PipelinePublicDTO>(
				dbPipelinePublicList.size());
		for (TPipelinePublic dbPipelinePublic : dbPipelinePublicList) {
			PipelinePublicDTO pipelinePublicDto = ConvertUtil.convertObj(
					dbPipelinePublic, PipelinePublicDTO.class);
			if (null != dbPipelinePublic.gettPipelineHeader()) {
				pipelinePublicDto.settPipelineHeader(ConvertUtil.convertObj(
						dbPipelinePublic.gettPipelineHeader(),
						PipelineHeaderDTO.class));
			}
			if (null != dbPipelinePublic.gettVendor()) {
				pipelinePublicDto.settVendor(ConvertUtil.convertObj(
						dbPipelinePublic.gettVendor(), VendorDTO.class));
			}
			rt.add(pipelinePublicDto);
		}
		return rt;
	}

	@Override
	public int updatePipelinePublic(List<PipelinePublicDTO> pipelinePublicList) {
		//
		int i = 0;
		if (Collections.isEmpty(pipelinePublicList))
			return i;
		Date now = new Date();
		String cUser = CurrentUserUtils.getInstance().getUsername();
		Long pipelineHeaderId = null;
		for (PipelinePublicDTO pupelinePublicDto : pipelinePublicList) {
			if (0 == i) {
				pipelineHeaderId = pupelinePublicDto.getPipelineHeaderId();
			}
			pipelinePublicRepository.updatePipelinePublic(
					pupelinePublicDto.getId(), pupelinePublicDto.getBidPrice(),
					pupelinePublicDto.getCommMark(),
					pupelinePublicDto.getTecMark(),
					pupelinePublicDto.getCompMark(),
					pupelinePublicDto.getFinalWin(),
					pupelinePublicDto.getSuggestedWin(), now, cUser);
			++i;
		}
		if (i > 0 && null != pipelineHeaderId && pipelineHeaderId > 0) {
			pipelineItemRepository.updatePipelineItemAccepted(true, now, cUser,
					pipelineHeaderId);
		}
		return i;
	}

	@Override
	public TPipelinePublic getPipelinePublicByPipelineIdAndWinflag(
			Long pipelineId, boolean suggestedWin, boolean finalWin) {

		return pipelinePublicRepository.findByPipelineIdAndWinflag(pipelineId,
				suggestedWin, finalWin);

	}

	/**
	 * 查找是否已经竞标过
	 * 
	 * @param pipelineHeader
	 * @param vendor
	 * @return
	 */
	public boolean ifAlreadyPipelined(TPipelineHeader pipelineHeader,
			TVendor vendor) {

		Session session = (org.hibernate.Session) em.getDelegate();
		Criteria criteria = session.createCriteria(TPipelinePublic.class)
				.add(Restrictions.eq("tPipelineHeader", pipelineHeader))
				.add(Restrictions.eq("tVendor", vendor));

		return criteria.list().isEmpty() ? false : true;
	}

	@Override
	public List<Long> findPipelineHeaderIdsByVendor(TVendor vendor) {

		List<TPipelinePublic> pipelinePublics = this.getByProperty("tVendor",
				vendor);
		List<Long> ids = new ArrayList<Long>();
		for (TPipelinePublic pipelinePublic : pipelinePublics) {
			ids.add(pipelinePublic.gettPipelineHeader().getId());
		}
		return ids;
	}

	@SuppressWarnings("unchecked")
	@Override
	public TPipelinePublic findByPipelineHeaderAndVendor(
			TPipelineHeader pipelineHeader, TVendor vendor) {

		Session session = (org.hibernate.Session) em.getDelegate();
		Criteria criteria = session.createCriteria(TPipelinePublic.class)
				.add(Restrictions.eq("tPipelineHeader", pipelineHeader))
				.add(Restrictions.eq("tVendor", vendor));

		List<TPipelinePublic> pipelinePublicList = criteria.list();
		if (!pipelinePublicList.isEmpty()) {
			return pipelinePublicList.get(0);
		}
		return null;
	}
}
